#ifndef SKY_BOX
#define SKY_BOX

#include <Define.h>
#include <osg/Group>
#include <osg/TextureCubeMap>
#include <osgUtil/CullVisitor>
#include <osg/TexMat>
#include <osg/ShapeDrawable>

class OSG_EDITOR_DLL SkyBox :	public osg::Group
{
public:

    class MoveEarthySkyWithEyePointTransform : public osg::Transform
    {
    public:
        /** Get the transformation matrix which moves from local coords to world coords.*/
        virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const
        {
            osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
            if (cv)
            {
                osg::Vec3 eyePointLocal = cv->getEyeLocal();
                matrix.preMult(osg::Matrix::translate(eyePointLocal));
            }
            return true;
        }

        /** Get the transformation matrix which moves from world coords to local coords.*/
        virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const
        {
            osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
            if (cv)
            {
                osg::Vec3 eyePointLocal = cv->getEyeLocal();
                matrix.postMult(osg::Matrix::translate(-eyePointLocal));
            }
            return true;
        }
    };

    struct TexMatCallback : public osg::NodeCallback
    {
    public:

        TexMatCallback(osg::TexMat& tm) :
            _texMat(tm)
        {
        }

        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
        {
            osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
            if (cv)
            {
                const osg::Matrix& MV = *(cv->getModelViewMatrix());
                const osg::Matrix R = osg::Matrix::rotate(osg::DegreesToRadians(112.0f), 0.0f, 0.0f, 1.0f)*
                        osg::Matrix::rotate(osg::DegreesToRadians(90.0f), 1.0f, 0.0f, 0.0f);

                osg::Quat q = MV.getRotate();
                const osg::Matrix C = osg::Matrix::rotate(q.inverse());

                _texMat.setMatrix(C*R);
            }

            traverse(node, nv);
        }

        osg::TexMat& _texMat;
    };
public:

    SkyBox(std::string& dir);
    SkyBox();
    ~SkyBox();

    //void build();

    osg::ref_ptr<osg::TextureCubeMap>  loadCubeMapTexture(const std::string& dir);

    void createSkyBox(const std::string& dir);
    void setImagePath(const std::string& back_image, const std::string& _front_image, const std::string& _down_image, const std::string& _up_image, const std::string& _right_image, const std::string& _left_image );
    void setBackImagePath(const std::string& back_image);
    void setFrontImagePath(const std::string& front_image);
    void setDownImagePath(const std::string& down_image);		void setUpImagePath(const std::string& up_image);
    void setRightImagePath(const std::string& right_image);
    void setLeftImagePath(const std::string& left_image);
    void createSkyBox();
    osg::ref_ptr<osg::TextureCubeMap>  loadCubeMapTexture();

protected:

    std::string             _dir;
    //std::vector<std::string> _cubemapDirs;
    osg::ref_ptr<osg::TextureCubeMap> _cubemap;
    std::string _back_image;
    std::string _front_image;
    std::string _down_image;
    std::string _up_image;
    std::string _right_image;
    std::string _left_image;

};



#endif //SKY_BOX
